﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace 多线程
{
    /// <summary>
    /// 异步调用必然使用到多线程，.net隐藏了多线程，采用.net线程池
    /// </summary>
    public partial class 异步处理 : Form
    {
        delegate int BinaryAdd(int a, int b);
        TestStruct t = null;
        BinaryAdd bAdd = null;
        public 异步处理()
        {
            InitializeComponent();
            t = new TestStruct();
            bAdd = new BinaryAdd(Add);
        }



        int Add(int a, int b)
        {
            Thread.Sleep(5000);
            int s = 0;
            int s2 = a / s;
            return a + b;
        }

        //非一步方式：阻塞调用者
        private void brnInvoke_Click(object sender, EventArgs e)
        {
            int r = bAdd.Invoke(1, 4);
        }

        //异步方式
        private void btnBeginInvoke_Click(object sender, EventArgs e)
        {
            //IAsyncResult:唯一区别每一次调用，可作为EndInvoke参数，获取调用的结果，调用完成的先后顺序不可预知
            IAsyncResult asyncResult= bAdd.BeginInvoke(56, 66, OnCallBack, t);
        }

        //回调函数
        void OnCallBack(IAsyncResult asyncResult)
        {
            //异步过程中异常，在回调函数中捕获，因为当EndInvoke时，会重新抛出这个异常，让客户端处理
            try
            {
                AsyncResult resultObj = asyncResult as AsyncResult;
                BinaryAdd badd = resultObj.AsyncDelegate as BinaryAdd;//获取到原委托实例
                TestStruct t = resultObj.AsyncState as TestStruct;//额外的参数
                int he = badd.EndInvoke(asyncResult);
                int s = t.T1;
                MessageBox.Show(he.ToString());
                asyncResult.AsyncWaitHandle.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnLunXun_Click(object sender, EventArgs e)
        {
            IAsyncResult asyncResult = bAdd.BeginInvoke(4, 6, null, null);

            while (!asyncResult.IsCompleted)
            {
              
            }

            int i = bAdd.EndInvoke(asyncResult);//用来获取输出参数和返回值，只能调用一次，参数接受IAsyncResult，确定是哪一次调用
            MessageBox.Show(i.ToString());
        }
    }

    public class TestStruct
    {
        int t1 = 8;

        public int T1
        {
            get { return t1; }
            set { t1 = value; }
        }
        int t2 = 5;

        public int T2
        {
            get { return t2; }
            set { t2 = value; }
        }
    }
}